package tt.love.hw.common.config;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;

public class AppContext {

	private Map<String, ObjectBean> beans = new HashMap<String, ObjectBean>();
	private Map<String, Object> beanInstance = new HashMap<String, Object>();

	public AppContext(InputStream in) {
		init(in);
		initBean();
	}

	private void init(InputStream in) {
		Digester digester = new Digester();
		digester.push(this);
		digester.setValidating(false);
		digester.addObjectCreate("beans/bean", ObjectBean.class);
		digester.addSetProperties("beans/bean");
		digester.addObjectCreate("beans/bean/property",
				ObjectBeanProperty.class);
		digester.addSetProperties("beans/bean/property");
		digester.addSetNext("beans/bean/property", "addProperty");
		digester.addSetNext("beans/bean", "addBean");
		try {
			digester.parse(in);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		}
	}

	private void initBean() {
		List<ObjectBean> beansWithProperty = new ArrayList<ObjectBean>();
		for (Map.Entry<String, ObjectBean> bean : beans.entrySet()) {
			if (!bean.getValue().getProperties().isEmpty()) {
				beansWithProperty.add(bean.getValue());
			}
			try {
				beanInstance.put(bean.getKey(), Class.forName(
						bean.getValue().getClazz()).newInstance());
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}

		for (ObjectBean beanWithProperty : beansWithProperty) {
			for (Map.Entry<String, ObjectBeanProperty> beanProperty : beanWithProperty
					.getProperties().entrySet()) {
				try {
					BeanUtils.setProperty(beanInstance.get(beanWithProperty.getId()), beanProperty
							.getKey(), beanInstance.get(beanProperty.getValue()
							.getRef()));
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}

			}
		}
	}

	public Object getBean(String beanId) {
		return beanInstance.get(beanId);

	}

	public void addBean(ObjectBean bean) {
		beans.put(bean.getId(), bean);
	}

	@Override
	public String toString() {
		return "AppContext [beans=" + beans + "]";
	}

}
